home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / editors / emacs / xemacs / xemacs-1.004 / xemacs-1 / xemacs-19.13 / src / EmacsShell-sub.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-08-07  |  12.9 KB  |  379 lines

  1. /* Emacs shell widget -- define the two widgets.
  2.    Copyright (C) 1994, 1995 Sun Microsystems, Inc.
  3.  
  4. This file is part of XEmacs.
  5.  
  6. XEmacs is free software; you can redistribute it and/or modify it
  7. under the terms of the GNU General Public License as published by the
  8. Free Software Foundation; either version 2, or (at your option) any
  9. later version.
  10.  
  11. XEmacs is distributed in the hope that it will be useful, but WITHOUT
  12. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14. for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with XEmacs; see the file COPYING.  If not, write to the Free
  18. Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /* Synched up with: Not in FSF. */
  21.  
  22. /* Written by Ben Wing, May, 1994. */
  23.  
  24. /*
  25.    It is rather unfortunate that we have to do this.  Blame those
  26.    short-sighted people who designed the monstrosities known as
  27.    Xt and ICCCM.
  28. */
  29.  
  30. /*
  31.    This widget is not actually Emacs-specific; perhaps there could
  32.    be a better name than "EmacsShell".  What it does is work around
  33.    a limitation in Xt in correctly dealing with the window-manager
  34.    size hints with applications that
  35.    
  36.    (a) dynamically change their window size
  37.    (b) have a cell size (width-inc and height-inc) other than 1
  38.  
  39.    and
  40.  
  41.    (c) cannot predict in advance exactly what size their shell will be
  42.        (This is the more common situation, when you have a number
  43.        of widgets, each with their own size ideas)
  44.  
  45.    This widget assumes that your program contains a fixed "base size"
  46.    plus some number of cells (e.g. character cells).  The WMShell
  47.    resources "widthInc" and "heightInc" specify the size of a
  48.    character cell, and the window manager will report the app's
  49.    size in cells rather than in pixels.
  50.  
  51.    If you use this widget, do not use the WMShell resources
  52.    "baseWidth", "baseHeight", "minWidth", or "minHeight".
  53.    Instead, use "widthCells" and "heightCells" to specify the
  54.    current size in cells (you must keep this up-to-date),
  55.    and "minWidthCells" and "minHeightCells" to specify the
  56.    minimum size in cells.
  57.    
  58.    Every time that the program issues a size command, the
  59.    "baseWidth", "baseHeight", "minWidth", and "minHeight" fields
  60.    of the WM_NORMAL_HINTS property will be updated to stay in
  61.    line with the resource values specified above.  The calculations
  62.    are done once the desired shell size is known but before the
  63.    window-manager size-change request is issued. (We must do it
  64.    at this time because before then we don't know what size we
  65.    will request, and after the request the deed has already
  66.    been done.)
  67.  
  68.    After you change the "baseWidth", "baseHeight", "minWidth",
  69.    or "minHeight" resources, you need to call
  70.    EmacsShellUpdateSizeHints() to manually update the size
  71.    hints, except in the following two circumstances:
  72.  
  73.    (a) you are about to make a geometry request.
  74.    (b) you are changing only "baseWidth" and "baseHeight"
  75.        from within a resize procedure.  (In this case,
  76.        the size hints are already correct.)
  77.  
  78. */
  79.  
  80. #include <config.h>
  81.  
  82. #include <stdio.h>
  83. #include <stdlib.h>
  84. #include <X11/StringDefs.h>
  85. #include "xintrinsicp.h"
  86. #include <X11/Shell.h>
  87. #include <X11/ShellP.h>
  88. #include <X11/Vendor.h>
  89. #include <X11/VendorP.h>
  90. #include "EmacsShellP.h"
  91.  
  92. #if defined (DEFINE_TOP_LEVEL_EMACS_SHELL)
  93. #define EMACS_SHELL_WIDGET TopLevelEmacsShellWidget
  94. #define SUPERCLASS_WIDGET_CLASS topLevelShellWidgetClass
  95. #define SUPERCLASS_CLASS_REC topLevelShellClassRec
  96. #define EMACS_SHELL_REC TopLevelEmacsShellRec
  97. #define EMACS_SHELL_CLASS_REC topLevelEmacsShellClassRec
  98. #define EMACS_SHELL_CLASS_REC_TYPE TopLevelEmacsShellClassRec
  99. #define EMACS_SHELL_CLASS_NAME "TopLevelEmacsShell"
  100. #define EMACS_SHELL_WIDGET_CLASS topLevelEmacsShellWidgetClass
  101. #define EMACS_SHELL_UPDATE_SIZE_HINTS TopLevelEmacsShellUpdateSizeHints
  102. #elif defined (DEFINE_TRANSIENT_EMACS_SHELL)
  103. #define EMACS_SHELL_WIDGET TransientEmacsShellWidget
  104. #define SUPERCLASS_WIDGET_CLASS transientShellWidgetClass
  105. #define SUPERCLASS_CLASS_REC transientShellClassRec
  106. #define EMACS_SHELL_REC TransientEmacsShellRec
  107. #define EMACS_SHELL_CLASS_REC transientEmacsShellClassRec
  108. #define EMACS_SHELL_CLASS_REC_TYPE TransientEmacsShellClassRec
  109. #define EMACS_SHELL_CLASS_NAME "TransientEmacsShell"
  110. #define EMACS_SHELL_WIDGET_CLASS transientEmacsShellWidgetClass
  111. #define EMACS_SHELL_UPDATE_SIZE_HINTS TransientEmacsShellUpdateSizeHints
  112. #else
  113. Error.  Must define either DEFINE_TOP_LEVEL_EMACS_SHELL or
  114. DEFINE_TRANSIENT_EMACS_SHELL.
  115. #endif
  116.  
  117. typedef struct {
  118.     XtPointer           next_extension;           
  119.     XrmQuark            record_type;             
  120.     long                version;
  121.     Cardinal            record_size;
  122. } GenericClassExtRec;
  123.  
  124. static XtGeometryResult RootGeometryManager (Widget gw,
  125.   XtWidgetGeometry *request, XtWidgetGeometry *reply);
  126. static void ChangeManaged (Widget w);
  127.  
  128. /* snarfed from Shell.c */
  129. #define BIGSIZE ((Dimension)32767)
  130.  
  131. static XtResource resources[] = {
  132. #define offset(field) XtOffset(EMACS_SHELL_WIDGET, emacs_shell.field)
  133. #define coreoffset(field) XtOffset(EMACS_SHELL_WIDGET, core.field)
  134. #ifdef LWLIB_USES_MOTIF
  135.   /* *** BOGOSITY^10! *** The Motif VendorShell fucks around with
  136.      the default values for X and Y, for no obvious reason.  This
  137.      causes Shell to indicate that the defaults of (0,0) were
  138.      program-specified, instead of letting the WM do what it wants. */
  139.   {XtNx, XtCPosition, XtRPosition, sizeof(Position),
  140.      coreoffset (x), XtRImmediate, (XtPointer)BIGSIZE},
  141.   {XtNy, XtCPosition, XtRPosition, sizeof(Position),
  142.      coreoffset (y), XtRImmediate, (XtPointer)BIGSIZE},
  143. #endif
  144.   { XtNwidthCells, XtCWidthCells, XtRInt, sizeof(int),
  145.       offset (width_cells), XtRImmediate, (XtPointer)0},
  146.   { XtNheightCells, XtCHeightCells, XtRInt, sizeof(int),
  147.       offset (height_cells), XtRImmediate, (XtPointer)0},
  148.   { XtNminWidthCells, XtCMinWidthCells, XtRInt, sizeof(int),
  149.       offset (min_width_cells), XtRImmediate, (XtPointer)0},
  150.   { XtNminHeightCells, XtCMinHeightCells, XtRInt, sizeof(int),
  151.       offset (min_height_cells), XtRImmediate, (XtPointer)0},
  152. };
  153.  
  154. static CompositeClassExtensionRec compositeClassExtRec = {
  155.     NULL,
  156.     NULLQUARK,
  157.     XtCompositeExtensionVersion,
  158.     sizeof(CompositeClassExtensionRec),
  159.     TRUE,
  160. };
  161.  
  162. static ShellClassExtensionRec shellClassExtRec = {
  163.     NULL,
  164.     NULLQUARK,
  165.     XtShellExtensionVersion,
  166.     sizeof(ShellClassExtensionRec),
  167.     RootGeometryManager
  168. };
  169.  
  170. EMACS_SHELL_CLASS_REC_TYPE EMACS_SHELL_CLASS_REC = {
  171.     { /*
  172.        *    core_class fields
  173.        */
  174.     /* superclass      */    (WidgetClass) &SUPERCLASS_CLASS_REC,
  175.     /* class_name      */    EMACS_SHELL_CLASS_NAME,
  176.     /* size          */    sizeof(EMACS_SHELL_REC),
  177.     /* Class Initializer  */    NULL,
  178.     /* class_part_initialize*/    NULL, /* XtInheritClassPartInitialize, */
  179.     /* Class init'ed ?      */    FALSE,
  180.     /* initialize      */    NULL,
  181.     /* initialize_notify  */    NULL,
  182.     /* realize          */    XtInheritRealize,
  183.     /* actions          */    NULL,
  184.     /* num_actions      */    0,
  185.     /* resources      */    resources,
  186.     /* resource_count      */    XtNumber (resources),
  187.     /* xrm_class      */    NULLQUARK,
  188.     /* compress_motion      */    FALSE,
  189.     /* compress_exposure  */    TRUE,
  190.     /* compress_enterleave*/    FALSE,
  191.     /* visible_interest      */    TRUE,
  192.     /* destroy          */    NULL,
  193.     /* resize          */    XtInheritResize,
  194.     /* expose          */    NULL,
  195.     /* set_values      */    NULL, /* XtInheritSetValues, */
  196.     /* set_values_hook      */    NULL,            
  197.     /* set_values_almost  */    XtInheritSetValuesAlmost,  
  198.     /* get_values_hook      */    NULL,            
  199.     /* accept_focus      */    NULL,
  200.     /* intrinsics version */    XtVersion,
  201.     /* callback offsets      */    NULL,
  202.     /* tm_table          */    NULL,
  203.     /* query_geometry      */    NULL,
  204.     /* display_accelerator*/    NULL,
  205.     /* extension      */    NULL
  206.   },{ /* Composite */
  207.     /* geometry_manager      */    XtInheritGeometryManager,
  208.     /* change_managed      */    ChangeManaged,
  209.     /* insert_child      */    XtInheritInsertChild,
  210.     /* delete_child      */    XtInheritDeleteChild,
  211.     /* extension      */    (XtPointer)&compositeClassExtRec
  212.   },{ /* Shell */
  213.     /* extension      */    (XtPointer)&shellClassExtRec
  214.   },{ /* WMShell */
  215.     /* extension      */    NULL
  216.   },{ /* VendorShell */
  217.     /* extension      */    NULL
  218.   },{ /* TopLevelShell or TransientShell */
  219.       /* both have exactly one XtPointer here. */
  220.     /* extension      */    NULL
  221.   },{ /* EmacsShell */
  222.     0
  223.   }
  224. };
  225.  
  226. WidgetClass EMACS_SHELL_WIDGET_CLASS = (WidgetClass) &EMACS_SHELL_CLASS_REC;
  227.  
  228. static void
  229. update_size_hints_internal (EMACS_SHELL_WIDGET w,
  230.                 int width, int height)
  231. {
  232.   int base_width, base_height;
  233.   int cell_width, cell_height;
  234.  
  235.   /* time to update them thar size hints */
  236.   cell_width = w->wm.size_hints.width_inc;
  237.   cell_height = w->wm.size_hints.height_inc;
  238.   base_width = width - cell_width * w->emacs_shell.width_cells;
  239.   base_height = height - cell_height * w->emacs_shell.height_cells;
  240. #ifdef DEBUG_GEOMETRY_MANAGEMENT
  241.   /* Very useful info when debugging geometry management problems.
  242.      When it's guaranteed that no more such problems exist, take
  243.      this stuff out. */
  244.   printf ("update_size_hints_internal:\n");
  245.   printf ("  actual pixel size: %d %d\n", width, height);
  246.   printf ("  cell size in pixels: %d %d\n", cell_width, cell_height);
  247.   printf ("  text area size in cells: %d %d\n", w->emacs_shell.width_cells,
  248.      w->emacs_shell.height_cells);
  249.   printf ("  base size set to: %d %d\n", base_width, base_height);
  250.   fflush (stdout);
  251. #endif
  252.   XtVaSetValues ((Widget) w,
  253.          XtNbaseWidth, base_width,
  254.          XtNbaseHeight, base_height,
  255.          XtNminWidth, base_width +
  256.          cell_width * w->emacs_shell.min_width_cells,
  257.          XtNminHeight, base_height +
  258.          cell_height * w->emacs_shell.min_height_cells,
  259.          NULL);
  260. }
  261.  
  262. static XtGeometryResult SuperClassRootGeometryManager (gw, request, reply)
  263.     Widget gw;
  264.     XtWidgetGeometry *request, *reply;
  265. {
  266.   ShellWidgetClass swc = (ShellWidgetClass) SUPERCLASS_WIDGET_CLASS;
  267.   ShellClassExtensionRec *scer;
  268.   GenericClassExtRec *gcer;
  269.  
  270.   /* find the shell extension record that specifies the
  271.      root geometry manager method */
  272.   for (gcer = (GenericClassExtRec *) swc->shell_class.extension;
  273.        gcer;
  274.        gcer = (GenericClassExtRec *) gcer->next_extension)
  275.     {
  276.       if (gcer->record_type == NULLQUARK)
  277.     break;
  278.     }
  279.  
  280.   if (!gcer)
  281.     abort ();
  282.  
  283.   /* call it to actually make the geometry request */
  284.   scer = (ShellClassExtensionRec *) gcer;
  285.   return (scer->root_geometry_manager)(gw, request, reply);
  286. }
  287.  
  288. static XtGeometryResult RootGeometryManager (gw, request, reply)
  289.     Widget gw;
  290.     XtWidgetGeometry *request, *reply;
  291. {
  292.   EMACS_SHELL_WIDGET w = (EMACS_SHELL_WIDGET) gw;
  293.   /* OK since this file is not dumped */
  294.   static int reentrant = 0;
  295.   XtGeometryResult result;
  296.  
  297.   if (reentrant)
  298.     abort ();
  299.   reentrant++;
  300.  
  301. #ifdef DEBUG_GEOMETRY_MANAGEMENT
  302.   printf ("root_geometry_manager:\n");
  303.   printf ("  current shell size: %d %d\n", w->core.width, w->core.height);
  304.   if (request->request_mode & CWWidth)
  305.     printf ("width requested;");
  306.   if (request->request_mode & CWHeight)
  307.     printf ("height requested;");
  308.   printf ("\n");
  309.   printf ("  requested shell size: %d %d\n", request->width, request->height);
  310. #endif
  311.   /* update the size hints */
  312.   update_size_hints_internal (w,
  313.                   request->request_mode & CWWidth ?
  314.                   request->width : w->core.width,
  315.                   request->request_mode & CWHeight ?
  316.                   request->height : w->core.height);
  317.  
  318.   result = SuperClassRootGeometryManager (gw, request, reply);
  319.  
  320. #ifdef DEBUG_GEOMETRY_MANAGEMENT
  321.   printf ("  result: %s\n",
  322.       result == XtGeometryYes ? "XtGeometryYes" :
  323.       result == XtGeometryNo ? "XtGeometryNo" :
  324.       result == XtGeometryAlmost ? "XtGeometryAlmost" :
  325.       "XtGeometryDone");
  326.   if (reply->request_mode & CWWidth)
  327.     printf ("width returned;");
  328.   if (reply->request_mode & CWHeight)
  329.     printf ("height returned;");
  330.   printf ("\n");
  331.   printf ("  resulting shell size: %d %d\n", reply->width, reply->height);
  332.   printf ("----------\n");
  333.   fflush (stdout);
  334. #endif
  335.   reentrant--;
  336.   return result;
  337. }
  338.  
  339. static void
  340. ChangeManaged (Widget wid)
  341. {
  342.   EMACS_SHELL_WIDGET w = (EMACS_SHELL_WIDGET) wid;
  343.  
  344.   /* If not realized, then we're being called from XtRealizeWidget().
  345.      RootGeometryManager() has not yet been called, and thus our
  346.      base size is incorrect.  We need to set it now or the Shell
  347.      will mess up geometry specifications with negative positional
  348.      offsets. */
  349.   if (!XtIsRealized (wid))
  350.     {
  351.       Widget child = NULL;
  352.       int i;
  353.       
  354.       /* the managed child indicates what our size is */
  355.       for (i = 0; i < w->composite.num_children; i++) {
  356.     if (XtIsManaged(w->composite.children[i])) {
  357.       child = w->composite.children[i];
  358.       break;
  359.     }
  360.       }
  361.       
  362.       update_size_hints_internal (w, child->core.width, child->core.height);
  363.     }
  364.  
  365.   /* call the real ChangeManaged */
  366.   (((ShellWidgetClass) SUPERCLASS_WIDGET_CLASS)->
  367.    composite_class.change_managed)(wid);
  368. }
  369.     
  370.  
  371. /******************* external entry points *********************/
  372.  
  373. void
  374. EMACS_SHELL_UPDATE_SIZE_HINTS (Widget gw)
  375. {
  376.   EMACS_SHELL_WIDGET w = (EMACS_SHELL_WIDGET) gw;
  377.   update_size_hints_internal (w, w->core.width, w->core.height);
  378. }
  379.